/*
 * Copyright (C) 2025 Tsingteng MicroSystem
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef _NFC_OSI_API_H_
#define _NFC_OSI_API_H_

#include "nfc_types.h"
#include "nfc_log_api.h"
#ifdef OSI_ALLOCATOR_DEBUG
#include "nfc_debug_api.h"
#endif
#include "osi_types.h"
#include <stdarg.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif

/**
 * @file nfc_osi_api.h
 * @brief OS相关接口API定义
*/

/** @brief 互斥锁状态 */
enum {
    MUTEX_STATE_NOT_INIT = 0,
    MUTEX_STATE_INITIALIZING,
    MUTEX_STATE_INITED,
    MUTEX_STATE_DESTROYING,
    MUTEX_STATE_STATIC,
};
#define MUTEX_INIT_VAL(name_str) {.state = MUTEX_STATE_NOT_INIT, .name = name_str}
/** @brief 线程入口函数类型 */
typedef void *(*tTHREAD_ENTRY)(void *);
/** @brief 线程创建参数 */
typedef struct {
    /** @brief 线程入口函数 */
    tTHREAD_ENTRY entry;
    /** @brief 线程名称 */
    const char* name;
    /** @brief 线程优先级，默认值为OS_DEFAULT_THREAD_PRIO */
    int priority;
    /** @brief 线程栈大小，0表示使用系统默认值 */
    uint16_t stack_size;
    /** @brief 传入线程入口的参数 */
    void* arg;
    /** @brief 线程结束后是否需要join获取返回值和回收资源，不需要线程返回值时填false让系统自动回收资源 */
    bool joinable;
} tTHREAD_PARAMS;

/**
 * @brief 分配所需的内存空间，并返回一个指向它的指针
 *
 * @param size 内存块的大小，单位：字节
 * @return 返回一个指针，指向已分配大小的内存。失败则返回NULL
*/
void* osi_malloc_inner(size_t size, const char *file, const char *func, int line);
static inline void* osi_malloc(size_t size)
{
    return osi_malloc_inner(size, __FILENAME__, __func__, __LINE__);
}

/**
 * @brief 分配所需的内存空间，并设置分配的内存为零，并返回一个指向它的指针
 *
 * @param size 内存块的大小，单位：字节
 * @return 返回一个指针，指向已分配大小的内存。失败则返回NULL
*/
void* osi_calloc_inner(size_t size, const char *file, const char *func, int line);
static inline void* osi_calloc(size_t size)
{
    return osi_calloc_inner(size, __FILENAME__, __func__, __LINE__);
}

/**
 * @brief 释放内存空间
 *
 * @param ptr 指针指向一个要释放内存的内存块，如果传递的参数是一个空指针，则不会执行任何动作
*/
void osi_free_inner(void* ptr);
#define osi_free(ptr) \
    osi_free_inner(ptr); \
    ptr = NULL

/**
 * @brief 分配一个帧结构内存空间
 *
 * @param element_size 帧结构的负载内存块大小，单位：字节
 * @return 返回一个指向帧结构的指针，失败则返回NULL
*/
tARRAY* osi_malloc_array_inner(size_t element_size, const char *file, const char *func, int line);
static inline tARRAY* osi_malloc_array(size_t element_size)
{
    return osi_malloc_array_inner(element_size, __FILENAME__, __func__, __LINE__);
}

/**
 * @brief 释放内存空间
 *
 * @param array 指针指向一个要释放的帧结构空间
*/
void osi_free_array_inner(tARRAY* array);
#define osi_free_array(array) \
    osi_free_array_inner(array);  \
    array = NULL

/**
 * @brief 初始化互斥锁
 *
 * @param mutex 互斥锁指针
 * @return 成功返回NFC_STATUS_OK，其他情况返回对应错误码
*/
tNFC_STATUS osi_mutex_init(tMUTEX *mutex);

/**
 * @brief 带参数初始化互斥锁
 *
 * @param mutex 互斥锁指针
 * @param is_recursive 是否是可重入锁，true：同一个线程可以多次加锁，false：同一个线程只能加锁一次
 * @return 成功返回NFC_STATUS_OK，其他情况返回对应错误码
*/
tNFC_STATUS osi_mutex_init_with_attr(tMUTEX *mutex, bool is_recursive);

/**
 * @brief 销毁互斥锁
 *
 * 销毁互斥锁，释放资源
 * @note 调用本函数前，确保所有的锁都已经释放
 *
 * @param mutex 互斥锁指针
 * @return 成功返回NFC_STATUS_OK，其他情况返回对应错误码
 *
*/
tNFC_STATUS osi_mutex_deinit(tMUTEX *mutex);
/**
 * @brief 获取互斥锁
 *
 * 获取互斥锁，如果互斥锁已经被其他线程获取，则当前线程进入阻塞状态
 *
 * @param mutex 互斥锁指针
 * @return 成功返回NFC_STATUS_OK，其他情况返回对应错误码
*/
tNFC_STATUS osi_mutex_lock(tMUTEX *mutex);
/**
 * @brief 尝试获取互斥锁
 *
 * 尝试获取互斥锁，如果互斥锁已经被其他线程获取，则当前线程不会进入阻塞状态
 *
 * @param 互斥锁指针
 * @return 成功获取锁返回NFC_STATUS_OK，其他情况返回对应错误码
*/
tNFC_STATUS osi_mutex_trylock(tMUTEX *mutex);
/**
 * @brief 获取互斥锁，超时还获取不到锁返回错误
 * @param mutex 互斥锁指针
 * @param timeout 超时时间，单位毫秒
 * @return 成功返回NFC_STATUS_OK
 *         超时返回NFC_STATUS_TIMEOUT
 *         其他情况返回对应错误码
 */
tNFC_STATUS osi_mutex_lock_timeout(tMUTEX *mutex, uint64_t timeout);
/**
 * @brief 释放互斥锁
 *
 * 释放互斥锁
 *
 * @param 互斥锁指针
 * @return 成功返回NFC_STATUS_OK，其他情况返回对应错误码
*/
tNFC_STATUS osi_mutex_unlock(tMUTEX *mutex);
/**
 * @brief 等待事件，直到被唤醒
 *
 * 调用后线程进入阻塞状态，等待其他线程调用osi_mutex_notify或是osi_mutex_notify_all唤醒
 *
 * @note 如果无线程调用osi_mutex_notify或是osi_mutex_notify_all唤醒，则线程一直处于阻塞状态
 * @note 调用此函数前需要先获取互斥锁
 *
 * @param mutex 互斥锁指针
 * @return 成功返回NFC_STATUS_OK，其他情况返回对应错误码
*/
tNFC_STATUS osi_mutex_wait_forever(tMUTEX *mutex);
/**
 * @brief 等待事件，直到被唤醒，无警告信息
 *
 * 调用后线程进入阻塞状态，等待其他线程调用osi_mutex_notify或是osi_mutex_notify_all唤醒
 *
 * @note 如果无线程调用osi_mutex_notify或是osi_mutex_notify_all唤醒，则线程一直处于阻塞状态
 * @note 调用此函数前需要先获取互斥锁
 *
 * @param mutex 互斥锁指针
 * @return 成功返回NFC_STATUS_OK，其他情况返回对应错误码
 */
tNFC_STATUS osi_mutex_wait_forever_no_warn(tMUTEX *mutex);
/**
 * @brief 等待事件，直到被唤醒或超时
 *
 * 调用后线程进入阻塞状态，等待其他线程调用osi_mutex_notify或是osi_mutex_notify_all唤醒或超时
 *
 * @note 调用此函数前需要先获取互斥锁
 *
 * @param mutex 互斥锁指针
 * @param timeout 超时时间，单位为毫秒
 * @return 成功返回NFC_STATUS_OK，超时返回NFC_STATUS_TIMEOUT，其他情况返回对应错误码
*/
tNFC_STATUS osi_mutex_wait(tMUTEX *mutex, uint64_t timeout);
/**
 * @brief 唤醒一个等待线程
 *
 * @note 调用此函数前需要先获取互斥锁
 *
 * @param mutex 互斥锁指针
 * @return 成功返回NFC_STATUS_OK，其他情况返回对应错误码
*/
tNFC_STATUS osi_mutex_notify(tMUTEX *mutex);
/**
 * @brief 唤醒所有等待线程
 *
 * @note 调用此函数前需要先获取互斥锁
 *
 * @param mutex 互斥锁指针
 * @return 成功返回NFC_STATUS_OK，其他情况返回对应错误码
*/
tNFC_STATUS osi_mutex_notify_all(tMUTEX *mutex);


/**
 * @brief 原子读
 * @param atomic 要操作的原子变量对象
 * @return 原子变量的值
 */
uint32_t osi_atomic_read(tATOMIC *atomic);

/**
 * @brief 原子写
 * @param atomic  要操作的原子变量对象
 * @param val     给原子变量更新的值
 */
void osi_atomic_write(tATOMIC *atomic, uint32_t val);

/**
 * @brief 原子先读再写值
 * @param atomic 要操作的原子变量对象
 * @param val    给原子变量更新的值
 * @return       原子变量更新之前的值
 */
uint32_t osi_atomic_read_then_write(tATOMIC *atomic, uint32_t val);

/**
 * @brief 原子加
 * @param atomic 要操作的原子变量对象
 * @param val    给原子变量值相加的值
 */
void osi_atomic_add(tATOMIC *atomic, uint32_t val);

/**
 * @brief 原子减
 * @param atomic 要操作的原子变量对象
 * @param val    给原子变量值相减的值
 */
void osi_atomic_sub(tATOMIC *atomic, uint32_t val);

/**
 * @brief 原子与
 * @param atomic 要操作的原子变量对象
 * @param val    给原子变量值做与操作的值
 */
void osi_atomic_and(tATOMIC *atomic, uint32_t val);

/**
 * @brief 原子或
 * @param atomic 要操作的原子变量对象
 * @param val    给原子变量值做或操作的值
 */
void osi_atomic_or(tATOMIC *atomic, uint32_t val);

/**
 * @brief 原子异或
 * @param atomic 要操作的原子变量对象
 * @param val    给原子变量值做异或操作的值
 */
void osi_atomic_xor(tATOMIC *atomic, uint32_t val);

/**
 * @brief 创建线程
 *
 * 根据参数配置并创建线程
 * 线程创建完成后即会启动，线程返回后资源会自动回收
 *
 * @param thread_id 线程句柄指针
 * @param params 线程创建参数
 *
 * @return 成功时返回NFC_STATUS_OK
 */
tNFC_STATUS osi_thread_create(tTHREAD *thread_id, const tTHREAD_PARAMS *params);

/**
 * @brief 等待线程终止
 *
 * 等待指定的线程终止，并收回其资源。
 *
 * @param thread_id 要等待的线程句柄
 * @param ret_val 线程返回值，不需要时传NULL
 *
 * @return 成功时返回NFC_STATUS_OK
 */
tNFC_STATUS osi_thread_join(tTHREAD thread_id, void **ret_val);

/** @brief 时间戳类型定义 */
typedef uint64_t tTIMESTAMP;

/**
 * @brief 获取当前系统时间戳，单位毫秒
 *
 * @param ms 返回时间戳
 *
 * @return 获取成功时返回NFC_STATUS_OK，失败时返回对应错误码
*/
tNFC_STATUS osi_curr_time_ms(tTIMESTAMP *ms);

/**
 * @brief 获取系统启动时间戳，单位毫秒
 *
 * @param ms 返回时间戳
 *
 * @return 获取成功时返回NFC_STATUS_OK，失败时返回对应错误码
*/
tNFC_STATUS osi_boot_time_ms(tTIMESTAMP *ms);

/**
 * @brief 睡眠指定时间
 *
 * @param us 睡眠时间，单位为微秒
*/
void osi_usleep(uint64_t us);

/**
 * @brief 输出DUMP信息
 *
 * @param fd 保存DUMP信息的文件描述符
 * @param fmt 格式化字符串
 * @param ... 可变参数，可变数量的参数根据fmt中的格式化指令进行格式化
 */
void osi_dump(int fd, const char *fmt, ...);

/**
 * @brief 安全的内存复制函数
 *
 * @param[out] dest   指向将要复制的目标内存的指针
 * @param[in]  destsz 复制目标内存的大小，单位：字节
 * @param[in]  src    指向复制目标原始内存的指针
 * @param[in]  count  需要复制内容的大小，单位：字节
 *
 * @return 成功返回true，其他情况返回false
*/
bool osi_memcpy(void *dest, size_t destsz, const void *src, size_t count);

/**
 * @brief 安全的内存设置函数
 *
 * @param[out] dest   指向将要被设置的目标内存的指针
 * @param[in]  destsz 将要被写入的目标内存大小，单位：字节
 * @param[in]  value  被写入的值
 * @param[in]  count  将要被写入的大小，单位：字节
 *
 * @return 成功返回true，其他情况返回false
*/
bool osi_memset(void *dest, size_t destsz, int value, size_t count);

/**
 * @brief 安全的字符串复制函数
 *
 * @param[out] dest   指向将要复制的目标内存的指针
 * @param[in]  destsz 复制目标内存的大小，单位：字节
 * @param[in]  src    指向复制目标原始内存的指针
 * @param[in]  count  需要复制内容的大小，单位：字节
 *
 * @return 成功返回true，其他情况返回false
*/
bool osi_strncpy(char *dest, size_t destsz, const char *src, const size_t count);

/**
 * @brief 安全的格式化输出字符串函数
 *
 * @param[out] str   目标字符串，用于存储格式化后的字符串的字符数组的指针
 * @param[in]  strsz 字符数组的大小，单位：字节
 * @param[out] count 输出到str缓冲区中的字符数，不包括字符串结尾的空字符'\0'，单位：字节
 * @param[in]  fmt   格式化字符串
 * @param[in]  args  可变参数，可变数量的参数根据fmt中的格式化指令进行格式化
 *
 * @return 成功返回true，其他情况返回false
*/
bool osi_snprintf(char *str, size_t strsz, int *count, const char *fmt, ...);

/**
 * @brief 安全的字符串连接函数
 *
 * @param dest      目标缓冲区
 * @param dest_size 目标缓冲区的总大小
 * @param src       源字符串
 * @param count     要复制的最大字符数
 * @return          true 成功，false 失败
 */
bool osi_strncat(char *dest, size_t dest_size, const char *src, size_t count);

#ifdef __cplusplus
};
#endif

#endif /* _NFC_OSI_API_H_ */
